package com.ioudi.digu.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.ioudi.digu.dao.support.IQuerySupport;
import com.ioudi.digu.service.support.ListResult;


public class GeneralDAO extends HibernateDaoSupport implements IGeneralDAO
{
    private IQuerySupport querySupport;
    
    private String className;
    
    private String idFieldName;
    
    private String orderFieldName;
    
	public String getClassName()
	{
		return className;
	}

	public void setClassName(String className)
	{
		this.className = className;
	}

	public String getIdFieldName()
	{
		return idFieldName;
	}

	public void setIdFieldName(String idFieldName)
	{
		this.idFieldName = idFieldName;
	}

	public String getOrderFieldName()
	{
		return orderFieldName;
	}

	public void setOrderFieldName(String orderFieldName)
	{
		this.orderFieldName = orderFieldName;
	}

	public IQuerySupport getQuerySupport()
	{
		return querySupport;
	}

	public void setQuerySupport(IQuerySupport querySupport)
	{
		this.querySupport = querySupport;
	}

	public Object saveObject(Object value)
	{
	   	if(value == null)
	   	{
	   		return value;
	   	}
        Session s = this.getSession();
        try
        {
	       	s.beginTransaction();
	       	s.saveOrUpdate(value);
	       	s.getTransaction().commit();
       }
       catch(Exception e)
       {
    	   value = null;
    	   s.getTransaction().rollback();
       }
       finally
       {
       		s.close();
       }
       return value;
	}
	
	public boolean deleteObjects(String[] ids)
	{
		boolean result = false;
        Session s = this.getSession();
        s.beginTransaction();
        try
        {
        	String sql = "delete " + getClassName() + " item where item." + getIdFieldName() + " in (:ids)";
        	s.createQuery(sql).setParameterList("ids", ids).executeUpdate();
        	s.getTransaction().commit();
        	result = true;
        }
        catch(Exception e)
        {
        	s.getTransaction().rollback();
        }
        finally
        {
        	s.close();
        }
        return result;
	}
	

	public List findObjects(int index, int maxCount, Map condition)
	{
		return findObjects("", index, maxCount, condition);
	}
	
	private  List findObjects(String selectSql, int index, int maxCount, Map condition)
	{
		String sql = selectSql + " from "  + getClassName() + " item ";
		List<String> keys = new ArrayList<String>();
		String statement = querySupport.createStatement("item", condition, keys);
		sql += statement.length() > 0 ? " where " + statement : "";
		sql += " order by item." + getOrderFieldName() +  " desc";
		return findObjectsInternal(index, maxCount, sql, keys, condition);
	}
	
	private List findObjectsInternal(int index, int maxCount, 
			String sql, List keys, Map condition)
	{
        Session s = this.getSession();
        s.beginTransaction();
        List result = null;
        try
        {
        	Query query  = s.createQuery(sql);
        	querySupport.createQuery(query, keys, condition);
        	query.setFirstResult(index);
        	if(maxCount > 0)
        	{
        		query.setMaxResults(maxCount);
        	}
        	result = query.list();
        	s.getTransaction().commit();
        }
        catch(Exception e)
        {
        	result = null;
        	s.getTransaction().rollback();
        }
        finally
        {
        	s.close();
        }
		return result;
	}

	public ListResult findObjectsWithTotal(int index, int maxCount,
			Map condition)
	{
		String sql = "from "  + getClassName() + " item ";
		List<String> keys = new ArrayList<String>();
		String statement = querySupport.createStatement("item", condition, keys);
		sql += statement.length() > 0 ? " where " + statement : "";
		sql += " order by item." + getOrderFieldName() +  " desc";
        Session s = this.getSession();
        s.beginTransaction();
        ListResult result = new ListResult();
        try
        {
        	Query query  = s.createQuery("select count(item) " + sql);
        	Object temp = querySupport.createQuery(query, keys, condition).uniqueResult();
        	int total = 0;
        	if(temp != null)
        	{
        		total = ((Long)temp).intValue();
        	}
        	result.setTotal(total);
        	
        	query = s.createQuery(sql);
        	querySupport.createQuery(query, keys, condition);
        	query.setFirstResult(index);
        	if(maxCount > 0)
        	{
        		query.setMaxResults(maxCount);
        	}
        	result.setContents(query.list());
        	s.getTransaction().commit();
        }
        catch(Exception e)
        {
        	result = null;
        	s.getTransaction().rollback();
        }
        finally
        {
        	s.close();
        }
		return result;
	}
	
	public List findFields(String fieldName, Map condition)
	{
		return findObjects("select distinct item." + fieldName, 0, -1, condition);
	}

	public Object getObject(String id)
	{
		Object item = null;
        Session s = this.getSession();
        try
        {
        	s.beginTransaction();
        	item = s.createQuery(
        			"from " + getClassName() + " item where item." + getIdFieldName() + "=:id").
        	    setString("id", id).uniqueResult();
        }
        catch(Exception e)
        {
        	item = null;
        	s.getTransaction().rollback();
        }
        finally
        {
        	s.close();
        }
        return item;
	}

	public Object updateObject(String id, Map condition)
	{
		Session s = this.getSession();
        boolean result = false;
        if(id == null || condition == null)
        {
        	return false;
        }
        List<String> keys = new ArrayList<String>();
        String sql = "update " + getClassName() + " item set ";
        sql += querySupport.createStatement("item", condition, keys);
        sql += " where item." + getIdFieldName() + " = ?";
        keys.add(getIdFieldName());
        condition.put(getIdFieldName(), id);
        try
        {
        	s.beginTransaction();
        	Query query = s.createQuery(sql);
        	querySupport.createQuery(query, keys, condition).executeUpdate();
        	s.getTransaction().commit();
        	result = true;
        }
        catch(Exception e)
        {
        	s.getTransaction().rollback();
        }
        finally
        {
        	s.close();
        }
	    return result;
    }
}
